﻿using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using StockholmsStad.Data.Interfaces;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;
using System;
using StockholmsStad.Utilities.Exceptions;
using StockholmsStad.Utilities;

namespace StockholmsStad.Data.Test
{
    /// <summary>
    /// Summary description for TestUnitIssue
    /// </summary>
    [TestClass]
    public class TestUnitTicket : TestUnitBase
    {
        // before running each test 
        [TestInitialize()]
        public void MyTestInitialize()
        {
            BeginTransaction();
        }

        // after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            EndTransaction();
        }

        [TestMethod]
        public void InsertAndRetrieveTicket()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var couple = TestEntity.GetNewCoupleWithoutContact();

            var agent = AgentFactory.GetLanguageAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = agent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = agent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            Ceremony ceremony = TestEntity.GetNewCeremony();
            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            User user = TestEntity.GetNewUser();

            var userAgent = AgentFactory.GetUserAgent();

            int userid = userAgent.CreateUser(context, user.Username, user.Password, (int) user.Role);
            Assert.AreNotEqual(0, userid, "Ingen användare skapades");

            const string information = "Litet mess";
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, userid);
            ticketAgent.InsertHistory(context, ticketId, information, user.Username, true);

            var expectedHistoryItems = ticketAgent.GetHistoryItems(context, ticketId, true);

            Assert.IsNotNull(expectedHistoryItems, "Ingen historik lades till ärendet");

            // Hämta det senaste ärendet (eftersom de sorteras på datum med äldsta först)
            History historyItem = expectedHistoryItems[expectedHistoryItems.Count - 1];

            Assert.IsNotNull(historyItem, "Fanns ingen historik för för paret");

            if(historyItem !=  null)
            {
                Assert.AreEqual(information, historyItem.Information, "Förväntat meddelande: {0} matchar inte erhållet: {1}", information, historyItem.Information);
                Assert.AreEqual(user.Username, historyItem.ModifiedByUser, "Förväntad user: {0} matchar inte erhållen: {1}", user.Username, historyItem.ModifiedByUser);
            }

            Assert.AreNotEqual(0, ticketId, "Ticket not created");

            Ticket ticket = ticketAgent.GetTicket(context, ticketId);

            // Assign added id´s
            couple.CoupleId = ticket.Couple.CoupleId;
            couple.Person1.PersonId = ticket.Couple.Person1.PersonId;
            couple.Person2.PersonId = ticket.Couple.Person2.PersonId;

            TestUnitPerson.ArePersonEqual(couple.Person1, ticket.Couple.Person1);
            TestUnitPerson.ArePersonEqual(couple.Person2, ticket.Couple.Person2);
            TestUnitCeremony.AreCeremonyEqual(ceremony, ticket.Ceremony);

            User userActual = userAgent.GetUser(context, user.Username);
            Assert.IsNotNull(userActual, string.Format("Finns ingen användare som heter {0}", user.Username));
            Assert.AreEqual(user.Username, userActual.Username);
            Assert.AreEqual(Enum.GetName(typeof(UserRole), user.Role), Enum.GetName(typeof(UserRole), userActual.Role), "Rollnamn matchade inte");
            Assert.AreEqual((int)user.Role, (int)userActual.Role, "Roll id matchade inte");
        }

        [TestMethod]
        public void CreateTicketAndRetrieveTicketIdFromUserName()
        {
            const int userRoleId = (int) UserRole.Customer;

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, "username", "password", userRoleId);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            var ticketAgent = AgentFactory.GetTicketAgent();
            var agent = AgentFactory.GetCeremonyAgent();

            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();

            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            int expectedTicketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);

            Assert.AreNotEqual(0, expectedTicketId, "Inget ärende skapades");

            var actualTicketId = ticketAgent.GetTicketId(context, "username");
            Assert.AreEqual(expectedTicketId, actualTicketId,
                            string.Format("Det förväntade id:t {0} stämde inte överens med det erhållna: {1}",
                                          expectedTicketId, actualTicketId));
        }

        [TestMethod]
        [ExpectedException(typeof(StockholmStadSystemException))]
        public void InsertTicketWithoutValidUser()
        {
            User user = TestEntity.GetNewUserWithoutUserName();
            var userAgent = AgentFactory.GetUserAgent();
            userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
        }

        [TestMethod]
        public void InsertAndRetrieveAndUpdateTicketInformation()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var agent = AgentFactory.GetCeremonyAgent();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();

            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony);

            Ticket ticket = ticketAgent.GetTicket(context, ticketId);

            Assert.IsNotNull(ticket, "Inget ärende skapades");
            Assert.AreEqual(ticket.Status, EnumUtility.GetEnumDescription(TicketStatusType.Started));
            
            // Assign added id´s
            couple.CoupleId = ticket.Couple.CoupleId;
            couple.Person1.PersonId = ticket.Couple.Person1.PersonId;
            couple.Person2.PersonId = ticket.Couple.Person2.PersonId;

            TestUnitPerson.ArePersonEqual(couple.Person1, ticket.Couple.Person1);
            TestUnitPerson.ArePersonEqual(couple.Person2, ticket.Couple.Person2);
            TestUnitCeremony.AreCeremonyEqual(ceremony, ticket.Ceremony);

            // Insert ticketinformation 
            const string text = "En liten textsträng";
            var ticketInfo = new TicketInformation {InformationText = text, TicketId = ticket.TicketId};
            int id = ticketAgent.AddTicketInformation(context, ticketInfo);

            Assert.AreNotEqual(0, id, "Ingen information lades till ärendet");

            var addedTicketInfo = ticketAgent.GetTicketInformation(context, ticketInfo.TicketId);
            AreTicketInfoEqual(ticketInfo, addedTicketInfo);

            const string newText = "Det här är en uppdaterad text";
            ticketInfo.InformationText = newText;
            ticketAgent.UpdateTicketInformation(context, ticketInfo);

            var updatedTicketInfo = ticketAgent.GetTicketInformation(context, ticketInfo.TicketId);
            AreTicketInfoEqual(ticketInfo, updatedTicketInfo);
        }

        [TestMethod]
        public void InsertAndRetrieveAndUpdateExtraLongTicketInformation()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var agent = AgentFactory.GetCeremonyAgent();

            var couple = TestEntity.GetNewCoupleWithoutContact();
            var ceremony = TestEntity.GetNewCeremony();

            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony);

            Ticket ticket = ticketAgent.GetTicket(context, ticketId);

            Assert.IsNotNull(ticket, "Inget ärende skapades");
            Assert.AreEqual(ticket.Status, EnumUtility.GetEnumDescription(TicketStatusType.Started));

            // Assign added id´s
            couple.CoupleId = ticket.Couple.CoupleId;
            couple.Person1.PersonId = ticket.Couple.Person1.PersonId;
            couple.Person2.PersonId = ticket.Couple.Person2.PersonId;

            TestUnitPerson.ArePersonEqual(couple.Person1, ticket.Couple.Person1);
            TestUnitPerson.ArePersonEqual(couple.Person2, ticket.Couple.Person2);
            TestUnitCeremony.AreCeremonyEqual(ceremony, ticket.Ceremony);

            // Insert ticketinformation 
            const string text = "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. "
                + "Detta är en extra lång textsträng. Detta är en extra lång textsträng. ";
            var ticketInfo = new TicketInformation { InformationText = text, TicketId = ticket.TicketId };
            int id = ticketAgent.AddTicketInformation(context, ticketInfo);

            Assert.AreNotEqual(0, id, "Ingen information lades till ärendet");

            var addedTicketInfo = ticketAgent.GetTicketInformation(context, ticketInfo.TicketId);
            AreTicketInfoEqual(ticketInfo, addedTicketInfo);

            const string newText = "Det här är en uppdaterad text";
            ticketInfo.InformationText = newText;
            ticketAgent.UpdateTicketInformation(context, ticketInfo);

            var updatedTicketInfo = ticketAgent.GetTicketInformation(context, ticketInfo.TicketId);
            AreTicketInfoEqual(ticketInfo, updatedTicketInfo);
        }

        private static void AreTicketInfoEqual(TicketInformation expexted, TicketInformation actual)
        {
            Assert.AreEqual(expexted.TicketId, actual.TicketId);
            Assert.AreEqual(expexted.InformationText, actual.InformationText);
        }

        [TestMethod]
        [ExpectedException(typeof (StockholmStadSystemException))]
        public void InsertAndRetrieveTicketWithNotValidLanguage()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            User user = TestEntity.GetNewUser();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();
            
            ceremony.CeremonyLanguage = new ValueIdPair {Name = TestEntity.NewLanguage};
            ceremony.CertificateLanguage = new ValueIdPair { Name = TestEntity.NewLanguage };

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            ticketAgent.CreateTicket(context, couple, ceremony, userId);
        }

        [TestMethod]
        public void InsertAndRetrieveTicketWithValidLanguage()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            User user = TestEntity.GetNewUser();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();

            ceremony.CeremonyLanguage = new ValueIdPair { Name = TestEntity.ExistingLanguage };
            ceremony.CertificateLanguage = new ValueIdPair { Name = TestEntity.ExistingLanguage };

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            int origNumOfTicket = ticketAgent.GetTickets(context, "","", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);
 
            Assert.AreNotEqual(0, ticketId);            
            int expected = origNumOfTicket + 1;

            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expected, retrievedNumOfTicket,
                            string.Format("Förväntat antal ticket {0} matchar inte erhållet antal tickets {1} ",
                                          expected, retrievedNumOfTicket));
        }

        [TestMethod]
        public void InsertAndRetrieveIndividualBookingWithImpedimentDates()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var ceremonyAgent = AgentFactory.GetCeremonyAgent();

            var user = TestEntity.GetNewUser();
            var couple = TestEntity.GetNewCoupleWithoutContact();
            var ceremony = TestEntity.GetNewCeremony();

            var agent = AgentFactory.GetCeremonyAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            var userAgent = AgentFactory.GetUserAgent();
            var userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            int origNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);

            Assert.AreNotEqual(0, ticketId);
            int expectedNoOfTickets = origNumOfTicket + 1;
            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expectedNoOfTickets, retrievedNumOfTicket,
                            string.Format("Förväntat antal ticket {0} matchar inte erhållet antal tickets {1} ",
                                          expectedNoOfTickets, retrievedNumOfTicket));

            var ceremonyId = ceremonyAgent.GetCeremonyId(context, ticketId);
            Assert.AreNotEqual(0, ceremonyId, "Ärendet hade ingen ceremoni");

            var addedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);
            
            TestUnitBooking.AreCeremonyEqual(ceremony, addedCeremony);

            // Add individual booking
            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            IBookingAgent bookingAgent = AgentFactory.GetBookingAgent();
            ministerAgent.AddMinister(context, TestEntity.GetNewMinister());
            Booking expectedBooking = TestEntity.GetIndividualBooking();
            int? ministerId = ministerAgent.GetMinisterIdByMinisterCode(context, expectedBooking.MinisterCode);

            var numOfBookings = 0;
            var bookings = ceremonyAgent.GetIndividualCeremonyBooking(context, expectedBooking.DateTime.StartDateTime.AddMonths(-1));

            if (bookings != null)
                numOfBookings = bookings.Count;

            bookingAgent.AddBooking(context, ticketId, expectedBooking, ministerId.Value);

            var bookingsAfterAdd = ceremonyAgent.GetIndividualCeremonyBooking(context, expectedBooking.DateTime.StartDateTime.AddMonths(-1));
            var bookingsForThatDay = ceremonyAgent.GetIndividualCeremonyBooking(context, expectedBooking.DateTime.StartDateTime, expectedBooking.DateTime.StartDateTime.AddDays(1), ministerId.Value);

            Assert.IsNotNull(bookingsForThatDay);
            Assert.AreNotEqual(0, bookingsForThatDay.Count, "Antal bokningar för dagen stämmer inte överens");

            Assert.AreNotEqual(numOfBookings, bookingsAfterAdd.Count, "antalet bokningar matchar inte");

            // Addera de förväntade värden på ceremoniobjektet som adderades
            var properties = AgentFactory.GetPropertiesAgent().GetProperties(context);
            
            ceremony.ImpedimentDocAllowDelayDays = 0;

            ceremonyAgent.UpdateCeremony(context, ceremonyId, ceremony);
            var retrievedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);

            TestUnitBooking.AreCeremonyEqual(ceremony, retrievedCeremony);

            Booking actualBooking = bookingAgent.GetBooking(context, ticketId);

            TestUnitBooking.AreBookingEqual(expectedBooking, actualBooking);
            var ticket = ticketAgent.GetTicket(context, ticketId);
            Assert.IsNotNull(ticket);
        }

        [TestMethod]
        [ExpectedException(typeof(StockholmStadSystemException))]
        public void InsertRetrieveAndRemoveIndividualBookingWithImpedimentDates()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var ceremonyAgent = AgentFactory.GetCeremonyAgent();

            var couple = TestEntity.GetNewCoupleWithoutContact();
            var ceremony = TestEntity.GetNewCeremony();

            int origNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony);

            Assert.AreNotEqual(0, ticketId);
            int expectedNoOfTickets = origNumOfTicket + 1;
            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expectedNoOfTickets, retrievedNumOfTicket,
                            string.Format("Förväntat antal ticket {0} matchar inte erhållet antal tickets {1} ",
                                          expectedNoOfTickets, retrievedNumOfTicket));

            var ceremonyId = ceremonyAgent.GetCeremonyId(context, ticketId);
            Assert.AreNotEqual(0, ceremonyId, "Ärendet hade ingen ceremoni");

            var addedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);

            TestUnitBooking.AreCeremonyEqual(ceremony, addedCeremony);

            // Add individual booking
            IMinisterAgent ministerAgent = AgentFactory.GetMinisterAgent();
            IBookingAgent bookingAgent = AgentFactory.GetBookingAgent();
            ministerAgent.AddMinister(context, TestEntity.GetNewMinister());
            Booking expectedBooking = TestEntity.GetIndividualBooking();
            int? ministerId = ministerAgent.GetMinisterIdByMinisterCode(context, expectedBooking.MinisterCode);

            bookingAgent.AddBooking(context, ticketId, expectedBooking, ministerId.Value);

            // Addera de förväntade värden på ceremoniobjektet som adderades
            var properties = AgentFactory.GetPropertiesAgent().GetProperties(context);
         
            ceremony.ImpedimentDocAllowDelayDays = 0;

            ceremonyAgent.UpdateCeremony(context, ceremonyId, ceremony);
            var retrievedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);

            TestUnitBooking.AreCeremonyEqual(ceremony, retrievedCeremony);

            Booking actualBooking = bookingAgent.GetBooking(context, ticketId);

            bookingAgent.RemoveBooking(context, ticketId, "testproj", couple.Person1.Email, "avboka");
            ceremonyAgent.UpdateCeremony(context, ceremonyId, retrievedCeremony);

            var removedBookingCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);
            TestUnitBooking.AreCeremonyEqual(retrievedCeremony, removedBookingCeremony);

            bookingAgent.GetBooking(context, ticketId);
        }

        [TestMethod]
        public void InsertAndRetrieveOrdinaryBookingWithImpedimentDates()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            User user = TestEntity.GetNewUser();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();

            ICeremonyAgent agent = AgentFactory.GetCeremonyAgent();

            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            int origNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);

            Assert.AreNotEqual(0, ticketId);
            int expectedNoOfTickets = origNumOfTicket + 1;

            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expectedNoOfTickets, retrievedNumOfTicket,
                            string.Format("Förväntat antal ticket {0} matchar inte erhållet antal tickets {1} ",
                                          expectedNoOfTickets, retrievedNumOfTicket));

            // Add ordinary booking
            var bookingAgent = AgentFactory.GetBookingAgent();
            var maintenanceAgent = AgentFactory.GetMaintenanceAgent();
            var ministerAgent = AgentFactory.GetMinisterAgent();

            int ministerId = ministerAgent.AddMinister(context, TestEntity.GetNewMinister());
            Assert.AreNotEqual(0, ministerId, "Ingen förrättare lades till");
            var minister = ministerAgent.GetMinister(context, ministerId);

            Assert.IsNotNull(minister, "Hittade inte förrättaren");            

            var timeblock = TestEntity.GetNewTimeBlock();
            timeblock.Minister = new Minister {MinisterId = ministerId};

            var timeblockId = maintenanceAgent.AddTimeBlock(context, timeblock);

            Booking expected = TestEntity.GetOrdinaryBooking();

            var numOfBookings = 0;
            var bookings = agent.GetOrdinaryCeremonyBooking(context, expected.DateTime.StartDateTime.AddMonths(-1));

            if (bookings != null)
                numOfBookings = bookings.Count;

            Booking expectedBooking = TestEntity.GetOrdinaryBooking();
            expectedBooking.MinisterCode = minister.MinisterCode;
            expected.DateTime.TimeBlockId = timeblockId;

            bookingAgent.AddBooking(context, ticketId, expected, ministerId);

            var bookingsAfterAdd = agent.GetOrdinaryCeremonyBooking(context, expected.DateTime.StartDateTime.AddMonths(-1));
            var bookingsForThatDay = agent.GetOrdinaryCeremonyBooking(context, expected.DateTime.StartDateTime, expected.DateTime.StartDateTime.AddDays(1), ministerId);

            Assert.AreNotEqual(numOfBookings, bookingsAfterAdd.Count, "antalet bokningar matchar inte");

            Assert.IsNotNull(bookingsForThatDay);
            Assert.AreNotEqual(0, bookingsForThatDay.Count, "Antal bokningar för dagen stämmer inte överens");

            Booking actual = bookingAgent.GetBooking(context, ticketId);

            TestUnitBooking.AreBookingEqual(expected, actual);

            var coupleAgent = AgentFactory.GetCoupleAgent();
 
            var coupleId = coupleAgent.GetCoupleId(context, userId);
            var ticketStatus = TicketStatusType.CarriedOut;
            ticketAgent.UpdateTicketStatus(context, ticketId, ticketStatus);
            var ticket = ticketAgent.GetTicket(context, ticketId);

            Assert.AreEqual(ticket.Status, EnumUtility.GetEnumDescription(ticketStatus), "Status matchar inte");
            Assert.IsNotNull(ticket);

            TestUnitBooking.AreCeremonyEqual(ceremony, ticket.Ceremony);
        }

        [TestMethod]
        public void InsertAndRetrieveOrdinaryBookingWithImpedimentDatesAndIssuedDate()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            User user = TestEntity.GetNewUser();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremonyWithImpedimentDates();

            var agent = AgentFactory.GetCeremonyAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            // Addera de förväntade värden på ceremoniobjektet som adderades
            var properties = AgentFactory.GetPropertiesAgent().GetProperties(context);

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;
            ceremony.ImpedimentDocIssuedDate = DateTime.Now;

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            int origNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);

            Assert.AreNotEqual(0, ticketId);

            var ticket = ticketAgent.GetTicket(context, ticketId);
            Assert.IsNotNull(ticket);

            int expectedNoOfTickets = origNumOfTicket + 1;

            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expectedNoOfTickets, retrievedNumOfTicket,
                            string.Format("Förväntat antal ticket {0} matchar inte erhållet antal tickets {1} ",
                                          expectedNoOfTickets, retrievedNumOfTicket));

            // Add ordinary booking
            IBookingAgent bookingAgent = AgentFactory.GetBookingAgent();

            var maintenanceAgent = AgentFactory.GetMaintenanceAgent();
            var timeblockId = maintenanceAgent.AddTimeBlock(context, TestEntity.GetNewTimeBlock());
            Assert.AreNotEqual(0, timeblockId, "Inget tidsblock skapades");
            Booking expected = TestEntity.GetOrdinaryBooking();
            expected.DateTime.TimeBlockId = timeblockId;

            bookingAgent.AddBooking(context, ticketId, expected, null);
            Booking actual = bookingAgent.GetBooking(context, ticketId);

            TestUnitBooking.AreBookingEqual(expected, actual);
            
            ceremony.ImpedimentDocAllowDelayDays = 0;

            TestUnitBooking.AreCeremonyEqual(ceremony, ticket.Ceremony);
        }

        [TestMethod]
        public void InsertRetrieveAndRemoveOrdinaryBookingWithImpedimentDates()
        {
            var ticketAgent = AgentFactory.GetTicketAgent();
            var ceremonyAgent = AgentFactory.GetCeremonyAgent();

            var couple = TestEntity.GetNewCoupleWithoutContact();
            var ceremony = TestEntity.GetNewCeremony();

            ICeremonyAgent agent = AgentFactory.GetCeremonyAgent();

            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            int origNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony);

            Assert.AreNotEqual(0, ticketId);
            int expectedNoOfTickets = origNumOfTicket + 1;

            int retrievedNumOfTicket = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();

            Assert.AreEqual(expectedNoOfTickets, retrievedNumOfTicket,
                            string.Format("Förväntat antal ärenden {0} matchar inte erhållet antal: {1} ",
                                          expectedNoOfTickets, retrievedNumOfTicket));

            // Are ceremony equal
            var ceremonyId = ceremonyAgent.GetCeremonyId(context, ticketId);
            var retrievedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);
            TestUnitBooking.AreCeremonyEqual(ceremony, retrievedCeremony);

            // Add ordinary booking
            IBookingAgent bookingAgent = AgentFactory.GetBookingAgent();

            var maintenanceAgent = AgentFactory.GetMaintenanceAgent();
            var timeblockId = maintenanceAgent.AddTimeBlock(context, TestEntity.GetNewTimeBlock());
            Booking expected = TestEntity.GetOrdinaryBooking();
            expected.DateTime.TimeBlockId = timeblockId;

            bookingAgent.AddBooking(context, ticketId, expected, null);

            // Addera de förväntade värden på ceremoniobjektet som adderades
            var properties = AgentFactory.GetPropertiesAgent().GetProperties(context);

            //ceremony.ImpedimentDocIssuedDate = DateTime.Now;
            ceremony.ImpedimentDocAllowDelayDays = 0;
            ceremony.ImpedimentDocEarliestDate =
                expected.DateTime.StartDateTime.AddMonths(-properties.ImpedimentDocValidMonths);
            ceremony.ImpedimentDocLatestDate = expected.DateTime.StartDateTime.AddDays(
                -properties.OrdinaryImpedimentDocRemoveBookingAtDays);

            ceremonyAgent.UpdateCeremony(context, ceremonyId, retrievedCeremony);

            var updatedCeremony = ceremonyAgent.GetCeremony(context, ceremonyId);
            TestUnitBooking.AreCeremonyEqual(ceremony, updatedCeremony);

            Booking actual = bookingAgent.GetBooking(context, ticketId);

            TestUnitBooking.AreBookingEqual(expected, actual);

            var ticket = ticketAgent.GetTicket(context, ticketId);
            Assert.IsNotNull(ticket);
        }

        [TestMethod]
        public void GetAllTickets()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            int defaultCount = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count;
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();


            var agent = AgentFactory.GetCeremonyAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            User user = TestEntity.GetNewUser();

            var userAgent = AgentFactory.GetUserAgent();
            int userId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            int createdTicketId = ticketAgent.CreateTicket(context, couple, ceremony, userId);
            CouplesSummaryItem[] tickets = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).ToArray();
            CouplesSummaryItem ticket = tickets.Where(t => t.TicketId == createdTicketId).First();

            Assert.IsNotNull(ticket);

            int newCount = tickets.Count();
            Assert.AreEqual(1, newCount - defaultCount);
            user.Username = "anotherUserName";

            int newUserId = userAgent.CreateUser(context, user.Username, user.Password, (int)user.Role);
            Assert.AreNotEqual(0, userId, "Ingen användare skapades");

            createdTicketId = ticketAgent.CreateTicket(context, couple, ceremony, newUserId);
            newCount = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count();
            Assert.AreEqual(2, newCount - defaultCount);
        }

        /// <summary>
        /// Do not check id
        /// </summary>
        /// <param name="expectedPerson"></param>
        /// <param name="retrievedPerson"></param>
        public static void ArePersonEqual(Person expectedPerson, Person retrievedPerson)
        {
            Assert.AreEqual(expectedPerson.FirstNames, retrievedPerson.FirstNames,
                            string.Format("Retrieved FirstNames ({0}) not the same as expected FirstNames ({1})",
                                          expectedPerson.FirstNames, retrievedPerson.FirstNames));
            Assert.AreEqual(expectedPerson.LastName, retrievedPerson.LastName,
                            string.Format("Retrieved LastName ({0}) not the same as expected LastName ({1})",
                                          expectedPerson.LastName, retrievedPerson.LastName));
            Assert.AreEqual(expectedPerson.PersonalNumber, retrievedPerson.PersonalNumber,
                            string.Format(
                                "Retrieved PersonalNumber ({0}) not the same as expected PersonalNumber ({1})",
                                expectedPerson.PersonalNumber, retrievedPerson.PersonalNumber));

            if (!retrievedPerson.Nationality.Equals("Svenskt"))
                Assert.AreEqual(expectedPerson.Nationality, retrievedPerson.Nationality,
                                string.Format("Retrieved Nationality ({0}) not the same as expected Nationality ({1})",
                                              expectedPerson.Nationality, retrievedPerson.Nationality));

            Assert.AreEqual(expectedPerson.SwedishNationality, retrievedPerson.SwedishNationality,
                            string.Format(
                                "Retrieved SwedishNationality ({0}) not the same as expected SwedishNationality ({1})",
                                expectedPerson.SwedishNationality, retrievedPerson.SwedishNationality));
            Assert.AreEqual(expectedPerson.ProtectedIdentity, retrievedPerson.ProtectedIdentity,
                            string.Format(
                                "Retrieved ProtectedIdentity ({0}) not the same as expected ProtectedIdentity ({1})",
                                expectedPerson.ProtectedIdentity, retrievedPerson.ProtectedIdentity));
            Assert.AreEqual(expectedPerson.PhoneNumber, retrievedPerson.PhoneNumber,
                            string.Format("Retrieved Phonenumber ({0}) not the same as expected Phonenumber ({1})",
                                          expectedPerson.PhoneNumber, retrievedPerson.PhoneNumber));
            Assert.AreEqual(expectedPerson.Email, retrievedPerson.Email,
                            string.Format("Retrieved Phonenumber ({0}) not the same as expected Phonenumber ({1})",
                                          expectedPerson.Email, retrievedPerson.Email));
            Assert.AreEqual(expectedPerson.Sex, retrievedPerson.Sex,
                            string.Format("Retrieved Sex ({0}) not the same as expected Sex ({1})", expectedPerson.Sex,
                                          retrievedPerson.Sex));
            if (expectedPerson.Address != null || retrievedPerson.Address != null)
                AreAddressEqual(expectedPerson.Address, retrievedPerson.Address);
        }

        public static void AreAddressEqual(Address expectedAddress, Address retrievedAddress)
        {
            Assert.AreEqual(expectedAddress.City, retrievedAddress.City,
                            string.Format("Retrieved city ({0}) not the same as expected city ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.CoAddress, retrievedAddress.CoAddress,
                            string.Format("Retrieved CoAddress ({0}) not the same as expected CoAddress ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.Country, retrievedAddress.Country,
                            string.Format("Retrieved Country ({0}) not the same as expected Country ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.PostCode, retrievedAddress.PostCode,
                            string.Format("Retrieved PostCode ({0}) not the same as expected PostCode ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.StreetAddress, retrievedAddress.StreetAddress,
                            string.Format("Retrieved StreetAddress ({0}) not the same as expected StreetAddress ({1})",
                                          expectedAddress.City, retrievedAddress.City));
        }

        /// <summary>
        /// Sorteringsordning på person1 efternamn
        /// </summary>
        [TestMethod]
        public void GetAllTickets3()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            int defaultCount = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started).Count;
            // Objects
            var couples = new Couple[3]
                                   {
                                       TestEntity.GetNewCoupleWithContact(),
                                       TestEntity.GetNewCoupleWithContact(),
                                       TestEntity.GetNewCoupleWithContact(),
                                   };
            var ceremony = TestEntity.GetNewCeremony();

            var agent = AgentFactory.GetCeremonyAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            var users = new User[3]
                               {
                                   TestEntity.GetNewUser(),
                                   TestEntity.GetNewUser(),
                                   TestEntity.GetNewUser(),
                               };
            int[] ticketIds = new int[3];
            couples[0].Person1.LastName = "Carlsson";
            couples[1].Person1.LastName = "Andersson";
            couples[2].Person1.LastName = "Bengtsson";

            var userAgent = AgentFactory.GetUserAgent();
            for (int i = 0; i < users.Length; i++)
            {
                User user = users[i];
                user.Username += i;
                int userId = userAgent.CreateUser(context, users[i].Username, users[i].Password, (int)UserRole.Customer);
                Assert.AreNotEqual(0, userId, "Ingen användare skapades");

                ticketIds[i] = ticketAgent.CreateTicket(context, couples[i], ceremony, userId);
            }
            // Expect
            IEnumerable<CouplesSummaryItem> tickets = ticketAgent.GetTickets(context, "", "", TicketStatusType.Started);
            int newCount = tickets.Count();
            Assert.AreEqual(3, newCount - defaultCount);
            tickets = tickets.Where(t => ticketIds.Contains(t.TicketId));
            Assert.AreEqual(3, tickets.Count());
            //Assert.AreEqual("Andersson", tickets.ElementAt(0).Couple.Person1.LastName);
            //Assert.AreEqual("Bengtsson", tickets.ElementAt(1).Couple.Person1.LastName);
            //Assert.AreEqual("Carlsson", tickets.ElementAt(2).Couple.Person1.LastName);
        }

        /// <summary>
        /// Testa att lösenord uppdateras
        /// </summary>
        [TestMethod]
        public void UpdateTicket()
        {
            ITicketAgent ticketAgent = AgentFactory.GetTicketAgent();
            IUserAgent userAgent = AgentFactory.GetUserAgent();
            Couple couple = TestEntity.GetNewCoupleWithoutContact();
            Ceremony ceremony = TestEntity.GetNewCeremony();

            var agent = AgentFactory.GetCeremonyAgent();
            var languageAgent = AgentFactory.GetLanguageAgent();
            var langId = languageAgent.AddLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, langId, "Inget nytt språk skapades");

            var cerLangId = languageAgent.AddCeremonyLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, cerLangId, "Inget nytt ceremoni språk skapades");

            var certLangId = languageAgent.AddCertificateLanguage(context, TestEntity.NewLanguage);
            Assert.AreNotEqual(0, certLangId, "Inget nytt certifikat språk skapades");

            ceremony.CeremonyLanguage.Id = cerLangId;
            ceremony.CertificateLanguage.Id = certLangId;

            int newUserId = userAgent.CreateUser(context, couple.Person1.Email, "passwd", (int)UserRole.Customer);
            Assert.AreNotEqual(0, newUserId, "Ingen användare skapades");

            int ticketId = ticketAgent.CreateTicket(context, couple, ceremony, newUserId);
            Assert.IsNotNull(ticketAgent.GetTicket(context, ticketId));
            Assert.IsNotNull(userAgent.GetUser(context, couple.Person1.Email));
            couple.Person1.Email = "uppd@mulli.nu";
            ticketAgent.UpdateTicket(context, ticketId, couple, ceremony, couple.Person1.Email);

            Ticket actual = ticketAgent.GetTicket(context, ticketId);
            Assert.AreEqual(couple.Person1.Email, actual.Couple.Person1.Email);
            User user = userAgent.GetUser(context, couple.Person1.Email);
            Assert.AreEqual(couple.Person1.Email, user.Username);
        }
    }
}